package com.gjy.encryption.asymmetric;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;

/**
 * ElGamal 加解密算法, jdk不提供, 使用的是 bouncy castle
 *
 * @author 宫静雨
 * @version 1.0
 * @since 2022-11-07 11:16:41
 */
public class ElGamalCoder {

    public ElGamalCoder(Integer size) {
        this.KEY_SIZE = size;
        initKey();
    }

    // 非对称加密算法
    private static final String KEY_ALGORITHM = "ElGamal";
    // 秘钥长度, 默认1024, 长度160-16384, 8的倍数
    private final Integer KEY_SIZE;
    private static final String PUBLIC_KEY = "ElGamalPublicKey";
    private static final String PRIVATE_KEY = "ElGamalPrivateKey";
    private static final HashMap<String, Key> map = new HashMap<>(4);

    /**
     * 私钥加密
     *
     * @param data 待加密数据
     * @return 加密数据
     * @throws Exception 异常
     */
    public byte[] encryptByPublicKey(byte[] data) throws Exception {
        // 取得私钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(getPublicKey());
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 生成私钥
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 私钥解密
     *
     * @param data 待解密数据
     * @return 解密数据
     * @throws Exception 异常
     */
    public byte[] decryptByPrivateKey(byte[] data) throws Exception {
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(getPrivateKey());
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 初始化 key
     */
    private void initKey() {
        try {
            // 添加 bouncy castle 依赖
            Security.addProvider(new BouncyCastleProvider());
            // 实例化算法参数生成器
            AlgorithmParameterGenerator apg = AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
            apg.init(KEY_SIZE);
            // 生成算法参数
            AlgorithmParameters parameters = apg.generateParameters();
            // 构建参数材料
            DHParameterSpec elParams = parameters.getParameterSpec(DHParameterSpec.class);
            // 实例化密钥对生成器
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            // 初始化密钥对生成器
            kpg.initialize(elParams, new SecureRandom());
            // 生成秘钥对
            KeyPair keyPair = kpg.generateKeyPair();
            map.put(PUBLIC_KEY, keyPair.getPublic());
            map.put(PRIVATE_KEY, keyPair.getPrivate());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private byte[] getPublicKey() {
        return map.get(PUBLIC_KEY).getEncoded();
    }

    private byte[] getPrivateKey() {
        return map.get(PRIVATE_KEY).getEncoded();
    }

    public interface Size {
        /**
         * 加密时间在1秒左右
         */
        Integer _256 = 256;
        /**
         * 加密时间在1分钟左右
         */
        Integer _1024 = 1024;
    }
}
